IF OBJECT_ID('ssf.dpnd_parse_object_header') IS NOT NULL
	DROP PROCEDURE ssf.dpnd_parse_object_header
GO

CREATE PROCEDURE ssf.dpnd_parse_object_header
	@object_name NVARCHAR(256)
	, @object_header XML (ssf.object_header) = NULL OUTPUT
AS
/*
<object_header>

<object_summary>
	<purpose><![CDATA[
Parse the object definition.
	]]></purpose>
</object_summary>

<parameter_dependency>
	<parameter_name>@object_name</parameter_name>
	<parameter_desc>Schema qualified object name.</parameter_desc>
	<data_type>NVARCHAR(256)</data_type>
	<return_type>INPUT</return_type>
</parameter_dependency>
<parameter_dependency>
	<parameter_name>@object_header</parameter_name>
	<parameter_desc>The xml documentation parsed from the object definition.</parameter_desc>
	<data_type>XML</data_type>
	<default_value>NULL</default_value>
	<return_type>INPUT/OUTPUT</return_type>
</parameter_dependency>

<input_dependency>
	<object_type>FUNCTION</object_type>
	<dpnd_object_name>ssf.regex_replace_singleline</dpnd_object_name>
</input_dependency>

</object_header>
*/

SET NOCOUNT ON

-- ============
/*<code_comment><![CDATA[declare dynamic sql variables]]></code_comment>*/
DECLARE	@proc_error INT
			, @sql_error INT
			, @error_message NVARCHAR(2048)
			, @error_line INT
			, @row_count BIGINT
			, @sql VARCHAR(8000) -- or (MAX)
			, @nsql NVARCHAR(4000) -- or (MAX)
			, @crlf CHAR(2) = CHAR(13) + CHAR(10)
			, @quote CHAR(1) = CHAR(39)
			, @tab CHAR(1) = CHAR(9)
-- ============

-- ============
/*<code_comment><![CDATA[declare local variables]]></code_comment>*/
DECLARE	@object_definition NVARCHAR(MAX)
			, @object_header_main XML
			, @object_comment XML
			, @object_summary_derived XML
			, @object_summary_element XML
			, @begin_tag NVARCHAR(128)
			, @end_tag NVARCHAR(128)
-- ============

-- ============
/*<code_comment><![CDATA[initialize output parameter]]></code_comment>*/
SET @object_header = NULL
-- ============

-- ============
/*<code_comment><![CDATA[exit if null, blank, or non-existent object name]]></code_comment>*/
IF NULLIF(@object_name, N'') IS NULL
OR OBJECT_ID(@object_name) IS NULL
	RETURN @@ERROR
-- ============

-- ============
/*<code_comment><![CDATA[get object definition]]></code_comment>*/
EXECUTE @proc_error = ssf.ddl_get_object_definition
	@object_name = @object_name
	, @object_definition = @object_definition OUTPUT

IF @proc_error <> 0
BEGIN
	RAISERROR('The call to the procedure <ssf.ddl_get_object_definition> failed.', 16, 1)
	RETURN @proc_error
END
-- ============

-- ============
/*<code_comment><![CDATA[begin: if object definition not null]]></code_comment>*/
IF @object_definition IS NOT NULL
BEGIN
	-- ============
	/*<code_comment><![CDATA[parse object definition for main header]]></code_comment>*/
	SET @object_header_main = CAST(ssf.regex_replace_singleline(
		@object_definition, '^.*?\<object_header\>(.*)\<\/object_header\>.*?$', '$1'
	) AS XML)
	-- ============
	
	-- ============
	/*<code_comment><![CDATA[parse object definition for comments]]></code_comment>*/
	SET @object_comment = (
		SELECT comment_sequence
			, CAST(code_comment AS XML)
		FROM (
			SELECT match_sequence + 1 AS comment_sequence
				, match_value AS code_comment
			FROM ssf.regex_matches_singleline(
				@object_definition, '(?>\<code_comment\>.*?\<\/code_comment\>)'
			)
		) c
		ORDER BY comment_sequence
		FOR XML PATH('object_comment'), TYPE
	)
	-- ============
END
/*<code_comment><![CDATA[end: if object definition not null]]></code_comment>*/
-- ============

-- ============
/*<code_comment><![CDATA[derive object summary]]></code_comment>*/
EXECUTE @proc_error = ssf.dpnd_derive_object_summary
	@object_name = @object_name
	, @object_summary = @object_summary_derived OUTPUT

IF @proc_error <> 0
BEGIN
	RAISERROR('The call to the procedure <ssf.dpnd_derive_object_summary> failed.', 16, 1)
	RETURN @proc_error
END
-- ============

-- ============
/*<code_comment><![CDATA[update main header]]></code_comment>*/
IF @object_header_main IS NULL
BEGIN
	SET @object_header_main = @object_summary_derived
END
ELSE
BEGIN
	IF (@object_header_main.exist('(/object_summary)[1]') = CAST(0 AS BIT))
		SET @object_header_main.modify('insert <object_summary/> as first into (/)[1]')

	SET @object_summary_element = @object_summary_derived.query('(/object_summary/dpnd_object_name)[1]')
	IF (@object_header_main.exist('(/object_summary/dpnd_object_name)[1]') = CAST(0 AS BIT))
		SET @object_header_main.modify('insert sql:variable("@object_summary_element") as first into (/object_summary)[1]')

	SET @object_summary_element = @object_summary_derived.query('(/object_summary/object_type)[1]')
	IF (@object_header_main.exist('(/object_summary/object_type)[1]') = CAST(0 AS BIT))
		SET @object_header_main.modify('insert sql:variable("@object_summary_element") after (/object_summary/dpnd_object_name)[1]')

	SET @object_summary_element = '<purpose/>'
	IF (@object_header_main.exist('(/object_summary/purpose)[1]') = CAST(0 AS BIT))
		SET @object_header_main.modify('insert sql:variable("@object_summary_element") after (/object_summary/object_type)[1]')

	SET @object_summary_element = @object_summary_derived.query('(/object_summary/return_data_type)[1]')
	IF (@object_header_main.exist('(/object_summary/return_data_type)[1]') = CAST(0 AS BIT))
		SET @object_header_main.modify('insert sql:variable("@object_summary_element") after (/object_summary/purpose)[1]')
END
-- ============

-- ============
/*<code_comment><![CDATA[construct xml output]]></code_comment>*/
BEGIN TRY
	SET @begin_tag = N'<' + N'object_header' + N'>'
	SET @end_tag = N'</' + N'object_header' + N'>'
	
	SET @object_header = CAST(
		@begin_tag
		+ CAST(@object_header_main AS NVARCHAR(MAX))
		+ ISNULL(CAST(@object_comment AS NVARCHAR(MAX)), N'')
		+ @end_tag
	AS XML)
END TRY
BEGIN CATCH
	SELECT @sql_error = ERROR_NUMBER()
		, @error_message = ERROR_MESSAGE()
	
	RAISERROR('Failed trying to construct xml output:%s%s', 16, 1, @crlf, @error_message)
	RETURN @sql_error
END CATCH
-- ============

RETURN @@ERROR
GO
